package com.lwl.concurrency.thread;

import java.time.LocalDateTime;
import java.util.concurrent.TimeUnit;

/**<pre>
 *   指定加锁对象:对给定对象加锁,进入同步代码前要获取给定对象的锁
 *   直接作用于实例方法:相当于对当前实例加锁,进入同步代码前要获得当前实例的锁
 *   直接作用于静态方法:相当于对当前类加锁,进入同步代码前要获得当前类的锁
 *
 *   同一时间,多个线程只能访问同一个实例对象中的一个synchronized成员方法,
 *   访问synchronized成员方法的同时可以访问一个且只能一个static synchronized静态方法
 *   非synchronized方法可以任意访问
 *
 *   减少在for循环中使用synchronized,因为获取锁的过程很耗时
 *   例如多个线程对同一个 int变量执行n次++操作,应当将synchronized放在for之外使用
 * </pre>
 * @author liwenlong - 2018/3/26 18:19
 */
public class SyncObj {

    public String syncObjMethod1() {
        System.out.println("before syncObjMethod1");
        synchronized (this) {
            System.out.println("syncObjMethod1 start..." + LocalDateTime.now().toString());
            try {
                TimeUnit.SECONDS.sleep(5);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("syncObjMethod1 end..." + LocalDateTime.now().toString());
            return "syncMethod1";
        }
    }

    public String syncObjMethod2() {
        System.out.println("before syncObjMethod2");
        synchronized (this) {
            System.out.println("syncObjMethod2 start..." + LocalDateTime.now().toString());
            try {
                TimeUnit.SECONDS.sleep(5);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("syncObjMethod2 end..." + LocalDateTime.now().toString());
            return "syncMethod2";
        }
    }

	public synchronized String syncMethod1() {
		System.out.println("syncMethod1 start..." + LocalDateTime.now().toString());
		try {
			TimeUnit.SECONDS.sleep(5);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println("syncMethod1 end..." + LocalDateTime.now().toString());
		return "syncMethod1";
	}

	public synchronized String syncMethod2() {
		System.out.println("syncMethod2 start..." + LocalDateTime.now().toString());
		try {
			TimeUnit.SECONDS.sleep(5);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println("syncMethod2 end..." + LocalDateTime.now().toString());
		return "syncMethod2";
	}

	public String noSyncMethod1() {
		System.out.println("noSyncMethod1 start..." + LocalDateTime.now().toString());
		try {
			TimeUnit.SECONDS.sleep(5);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println("noSyncMethod1 end..." + LocalDateTime.now().toString());
		return "noSyncMethod1";
	}

	public String noSyncMethod2() {
		System.out.println("noSyncMethod2 start..." + LocalDateTime.now().toString());
		try {
			TimeUnit.SECONDS.sleep(5);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println("noSyncMethod2 end..." + LocalDateTime.now().toString());
		return "noSyncMethod2";
	}

    public static synchronized String staticSyncMethod1() {
        System.out.println("staticSyncMethod1 start..." + LocalDateTime.now().toString());
		try {
			TimeUnit.SECONDS.sleep(5);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println("staticSyncMethod1 end..." + LocalDateTime.now().toString());
		return "staticSyncMethod1";
	}

    public static synchronized String staticSyncMethod2() {
        System.out.println("staticSyncMethod2 start..." + LocalDateTime.now().toString());
		try {
			TimeUnit.SECONDS.sleep(5);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println("staticSyncMethod2 end..." + LocalDateTime.now().toString());
		return "staticSyncMethod2";
	}

	public String staticNoSyncMethod1() {
		System.out.println("staticNoSyncMethod1 start..." + LocalDateTime.now().toString());
		try {
			TimeUnit.SECONDS.sleep(5);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println("staticNoSyncMethod1 end..." + LocalDateTime.now().toString());
		return "staticNoSyncMethod1";
	}

	public String staticNoSyncMethod2() {
		System.out.println("staticNoSyncMethod2 start..." + LocalDateTime.now().toString());
		try {
			TimeUnit.SECONDS.sleep(5);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println("staticNoSyncMethod2 end..." + LocalDateTime.now().toString());
		return "staticNoSyncMethod2";
	}

}
